package main;

//Nikolas Wolfe
//2/9/2009
//CIS 4930
//Towers of Hanoi

/*
* Hopefully this works
*/

public class ConcreteSmarterExecution implements ExecutionStrategy
{
	private TowerWatcher c;

	public ConcreteSmarterExecution(TowerWatcher c)
	{
		this.c = c;
	}
	
	public void run()
	{
		while( !Thread.interrupted() )
		{
			try
			{
				/* For a given tower, the rule is:
				 * 1.) If a valid move exists,
				 * 2.) If the move is not onto the previous tower
				 *     that the disk belonged
				 * 3.) If the tower is not empty and the move is 
				 * 	   valid, do it
				 * 4.) If the tower is empty and the move is 
				 *     valid, do it
				 */
				if( legalMoveExists() && !c.getToh().checkIfSolved() )
				{
					// TRY NON-EMPTY TOWERS
					// look right...
					// prioritize non-empty towers
					if( !rightTowerIsEmpty() )
					{
						// is this the previous tower we moved to?
						if( !rightTowerIsPreviousTower() )
						{
							tryMoveRight();
							registerMoves();
						}
					}
					// look left...
					// prioritize non-empty towers
					if( legalMoveExists() && !leftTowerIsEmpty() )
					{
						// is this the previous tower we moved to?
						if( !leftTowerIsPreviousTower() )
						{
							tryMoveLeft();
							registerMoves();
						}
					}
					
					// TRY EMPTY TOWERS
					// look right...
					// prioritize empty towers
					if( legalMoveExists() && rightTowerIsEmpty() )
					{
						// is this the previous tower we moved to?
						if( !rightTowerIsPreviousTower() )
						{
							tryMoveRight();
							registerMoves();
						}
					}
					// look left...
					// prioritize empty towers
					if( legalMoveExists() && leftTowerIsEmpty() )
					{
						// is this the previous tower we moved to?
						if( !leftTowerIsPreviousTower() )
						{
							tryMoveLeft();
							registerMoves();
						}
					}
				}
			} 
			catch( InterruptedException e )
			{
				// set the flag to exit the while loop
				// at the start of the next iteration
				Thread.currentThread().interrupt();
			}
		}
	}
	
	public void registerMoves() throws InterruptedException
	{
		// yield if done
		c.checkToYieldAction();
		c.getToh().checkReadyToYield(c.getMyTower());
	}
	
	public boolean legalMoveExists() throws InterruptedException
	{
		return c.getToh().hasLegalMove(c.getMyTower(), c.toString());
	}
	
	/* -------------------
	 * Right Tower Methods
	 * -------------------
	 */
	public boolean rightTowerIsPreviousTower()
	{
		// don't repeat previous moves from the right
		Disk pd;
		HanoiTower ht = c.getMyTower();
		if( !(ht.isEmpty()) && !((pd = ht.peekTower()) == null) )
		{
			HanoiTower rt = c.getMyTower().getRightTower();
			return pd.getPrevTower().equals(rt); // right tower is previous tower
		}
		else{ return true; } // might as well be!
	}
	
	public boolean rightTowerIsEmpty()
	{
		return c.getMyTower().getRightTower().isEmpty();
	}
	
	public boolean tryMoveRight() throws InterruptedException
	{
		if(c.getToh().moveDiskRight(c.getMyTower(), c.toString()))
		{
			c.setActionCount(c.getActionCount()+1);
			return true;
		}
		else { return false; }
	}
	
	/* ------------------
	 * Left Tower Methods
	 * ------------------
	 */
	public boolean leftTowerIsPreviousTower()
	{
		// don't repeat previous moves from the left
		Disk pd;
		HanoiTower ht = c.getMyTower();
		if( !(ht.isEmpty()) && !((pd = ht.peekTower()) == null) )
		{
			HanoiTower lt = c.getMyTower().getLeftTower();
			return pd.getPrevTower().equals(lt); // left tower is previous tower
		}
		else{ return true; } // might as well be!
	}
	
	public boolean leftTowerIsEmpty()
	{
		return c.getMyTower().getLeftTower().isEmpty();
	}
	
	public boolean tryMoveLeft() throws InterruptedException
	{
		if(c.getToh().moveDiskLeft(c.getMyTower(), c.toString()))
		{
			c.setActionCount(c.getActionCount()+1);
			return true;
		}
		else { return false; }
	}
}

